using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Drawing.Design;
using System.Runtime.Serialization;
using OpenComposite.Workflow.Properties;

namespace OpenComposite.Workflow
{
	[Designer(typeof(ExclusiveORDesigner))]
	[ToolboxItem(typeof(ExclusiveORActivityToolboxItem))]
	[ToolboxBitmap(typeof(resfinder), "OpenComposite.Workflow.Resources.toolbox_xor.png")]
	public partial class ExclusiveORActivity : DecisionActivity
	{
		protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
		{
			//if (Root.RunType == RunType.Analytic) {
			//    return base.Execute(executionContext);
			//} else if (Root.RunType == RunType.RandomDocuments) {
			if ( EnabledActivities.Count == 0 )
				return ActivityExecutionStatus.Closed;

			HorizontalWorkflowActivity root = WorkflowHelpers.GetRootActivity(this) as HorizontalWorkflowActivity;
			if ( root.UserData[Resources.sJumpData] != null ) {
				List<string> path = root.UserData[Resources.sJumpData] as List<string>;
				Activity act = GetActivityByName(path[0]);
				act.Closed += ContinueAt;
				executionContext.ExecuteActivity(act);
				path.RemoveAt(0);
				if ( path.Count == 0 )
					root.UserData.Remove(Resources.sJumpData);
			} else {
				foreach ( Activity child in EnabledActivities ) {
					ActivityCondition condition = child.GetValue(ConditionalBranchActivity.RuleProperty) as ActivityCondition;
					if ( condition == null || condition.Evaluate(child, executionContext) == true ) {
						child.Closed += ContinueAt;
						executionContext.ExecuteActivity(child);
						break;
					}
				}
			}
			return ActivityExecutionStatus.Executing;
			//} else {
			//    return ActivityExecutionStatus.Closed;
			//}
		}

		void ContinueAt(object sender, ActivityExecutionStatusChangedEventArgs e)
		{
			e.Activity.Closed -= this.ContinueAt;
			ActivityExecutionContext context = sender as ActivityExecutionContext;
			foreach ( ActivityExecutionContext ctx in context.ExecutionContextManager.ExecutionContexts ) {
				if ( ctx.Activity.ExecutionStatus == ActivityExecutionStatus.Executing )
					ctx.CancelActivity(ctx.Activity);
			}
			WorkflowHelpers.SecureCloseContext(context);
		}

		protected override ActivityExecutionStatus HandleFault(ActivityExecutionContext executionContext, Exception exception)
		{
			return base.HandleFault(executionContext, exception);
		}

		protected override ActivityExecutionStatus Cancel(ActivityExecutionContext executionContext)
		{
			return base.Cancel(executionContext);
		}
	}

	public partial class ExclusiveORDesigner : DecisionDesigner
	{
		private Pen innerSymbolPenM = new Pen(Brushes.Black, 3.0F);
		private SizeF s = SizeF.Empty;

		#region Paint Methods
		protected override void PaintSplit(ActivityDesignerPaintEventArgs e)
		{
			base.PaintSplit(e);

			if ( s == SizeF.Empty )
				s = e.Graphics.MeasureString("XOR", TextFont).ToSize();

			e.Graphics.DrawString("XOR",
				TextFont,
				e.DesignerTheme.ForegroundBrush,
				new PointF(WorkflowHelpers.GetCenter(bounds).X + 2 - ( s.Width / 2 ),
					WorkflowHelpers.GetCenter(bounds).Y - ( s.Height / 2 )));

			//int x1 = bounds.Left;
			//int x2 = bounds.Right;
			//int y1 = bounds.Top;
			//int y2 = bounds.Bottom;
			//e.Graphics.DrawLine(innerSymbolPenM, x1, y1, x2, y2); // draw horizontal line
			//e.Graphics.DrawLine(innerSymbolPenM, x2, y1, x1, y2); // draw vertical line
		}

		protected override void PaintJoin(ActivityDesignerPaintEventArgs e)
		{
			base.PaintJoin(e);

			//if (s == SizeF.Empty)
			//    s = e.Graphics.MeasureString("XOR", TextFont);

			//e.Graphics.DrawString("XOR",
			//    TextFont,
			//    e.DesignerTheme.ForegroundBrush,
			//    new PointF(WorkflowHelpers.GetCenter(bounds).X + 2 - (s.Width / 2),
			//        WorkflowHelpers.GetCenter(bounds).Y - (s.Height / 2)));
			//bounds.Inflate(-13, -13);

			//int x1 = bounds.Left;
			//int x2 = bounds.Right;
			//int y1 = bounds.Top;
			//int y2 = bounds.Bottom;
			//e.Graphics.DrawLine(innerSymbolPenM, x1, y1, x2, y2); // draw horizontal line
			//e.Graphics.DrawLine(innerSymbolPenM, x2, y1, x1, y2); // draw vertical line
		}
		#endregion

		protected override Pen ConnectorPen
		{
			get { return new Pen(Color.DarkGreen); }
		}
		protected override SolidBrush JoinBrush
		{
			get { return (SolidBrush)Brushes.DarkGreen; }
		}
		protected override LinearGradientBrush BackgroundBrush
		{
			get
			{
				Point start = new Point(bounds.Top + Bounds.Height / 2, bounds.Top);
				Point end = new Point(bounds.Top + Bounds.Height / 2, bounds.Bottom);
				return new LinearGradientBrush(start, end, Color.White, Color.Green);
			}
		}

		protected override void Dispose(bool disposing)
		{
			innerSymbolPenM.Dispose();

			base.Dispose(disposing);
		}

		public override bool CanInsertActivities(HitTestInfo insertLocation, ReadOnlyCollection<Activity> activitiesToInsert)
		{
			if ( activitiesToInsert.Count == 0 )
				return false;

			if ( activitiesToInsert[0] is ConditionalBranchActivity )
				return true;
			else
				return false;
		}
	}

	[Serializable]
	public class ExclusiveORActivityToolboxItem : ActivityToolboxItem
	{
		public ExclusiveORActivityToolboxItem(Type type)
			: base(type)
		{
			this.DisplayName = "Exclusive Or";
		}

		private ExclusiveORActivityToolboxItem(SerializationInfo info, StreamingContext context)
		{
			Deserialize(info, context);
		}
	}
}